package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.commom.web.feign.PaymentFeignService;
import com.tiancheng.trade.commom.web.model.response.PaymentChannelResponseDTO;
import com.tiancheng.trade.settlement.bo.PaymentChannelBO;
import com.tiancheng.trade.settlement.enums.InvoiceTypeEnum;
import com.tiancheng.trade.settlement.enums.OrderSourceEnum;
import com.tiancheng.trade.settlement.enums.PaymentChannelEnum;
import com.tiancheng.trade.settlement.exception.BusinessException;
import com.tiancheng.trade.settlement.mapper.settlement.MerchantContractMapper;
import com.tiancheng.trade.settlement.model.settlement.MerchantContract;
import com.tiancheng.trade.settlement.service.settlement.IMerchantContractService;
import com.tiancheng.trade.settlement.util.ExcelUtil;
import com.tiancheng.trade.settlement.util.ObjectConvertUtil;
import com.tiancheng.trade.settlement.vo.settlement.merchantcontract.GetMerchantContractVO;
import com.tiancheng.trade.settlement.vo.settlement.merchantcontract.GetPageMerchantContractVO;
import com.tiancheng.trade.settlement.vo.settlement.merchantcontract.MerchantContractExpVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.NumberFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MerchantContractService implements IMerchantContractService {

    @Autowired
    private MerchantContractMapper merchantMapper;

    @Autowired
    private PaymentFeignService paymentService;

    public MerchantContract findById(Long id) {
        MerchantContract merchant = merchantMapper.selectById(id);
        if (null != merchant) {

            Result<List<PaymentChannelResponseDTO>> channelBOList = paymentService.getAllChannel();
            List<PaymentChannelResponseDTO> channelList = new ArrayList<PaymentChannelResponseDTO>();
            if (channelBOList.getRet() == 0) {
                channelList = channelBOList.getData();
            }
            if (StringUtils.isNotEmpty(merchant.getPayChannel()) && CollectionUtils.isNotEmpty(channelList)) {
                List<PaymentChannelResponseDTO> filterList = channelList.stream().filter(c -> c.getPaymentChannelCode().equals(merchant.getPayChannel())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(filterList)) {
                    merchant.setPayChannelCn(filterList.get(0).getPaymentChannelName());
                }
            }
            merchant.setInvoiceTypeCn(InvoiceTypeEnum.getDesc(merchant.getInvoiceType()));
            //merchant.setPayChannelCn(PaymentChannelEnum.getDesc(merchant.getPayChannel()));
            merchant.setOrderSourceCn(OrderSourceEnum.getDesc(merchant.getOrderSource()));
        }
        return merchant;
    }

    @Override
    public PageInfo<MerchantContract> getMerchantPage(GetPageMerchantContractVO merchantVO) {
        QueryWrapper<MerchantContract> conditions = new QueryWrapper<MerchantContract>();
        conditions.eq("is_delete", false);
        if (StringUtils.isNotBlank(merchantVO.getContractCode())) {
            conditions.eq("contract_code", merchantVO.getContractCode());
        }
        if (StringUtils.isNotBlank(merchantVO.getOrganizationName())) {
            conditions.like("organization_name", merchantVO.getOrganizationName());
        }
        if (StringUtils.isNotBlank(merchantVO.getMerchantName())) {
            conditions.like("merchant_name", merchantVO.getMerchantName());
        }
        if (StringUtils.isNotBlank(merchantVO.getOrderSource())) {
            conditions.eq("order_source", merchantVO.getOrderSource());
        }
        if (StringUtils.isNotBlank(merchantVO.getPayChannel())) {
            conditions.eq("pay_channel", merchantVO.getPayChannel());
        }
        if (StringUtils.isNotBlank(merchantVO.getInvoiceType())) {
            conditions.eq("invoice_type", merchantVO.getInvoiceType());
        }
        if (StringUtils.isNotBlank(merchantVO.getContractSignDate())) {
            conditions.eq("contract_sign_date", merchantVO.getContractSignDate());
        }
        if (StringUtils.isNotBlank(merchantVO.getContractStartDate())) {
            conditions.le("contract_start_date", merchantVO.getContractStartDate());
        }
        if (StringUtils.isNotBlank(merchantVO.getContractEndDate())) {
            conditions.ge("contract_end_date", merchantVO.getContractEndDate());
        }
        conditions.orderByDesc("created_dt");

        PageInfo<MerchantContract> pageInfo = merchantMapper.find(conditions, merchantVO.getCurrentPage(), merchantVO.getPageSize());
        List<MerchantContract> list = pageInfo.getList();
        if (CollectionUtils.isNotEmpty(list)) {
            //取支付渠道
            Result<List<PaymentChannelResponseDTO>> channelBOList = paymentService.getAllChannel();
            List<PaymentChannelResponseDTO> channelList = new ArrayList<PaymentChannelResponseDTO>();
            if (channelBOList.getRet() == 0) {
                channelList = channelBOList.getData();
            }
            for (MerchantContract constract : list) {
                if (StringUtils.isNotEmpty(constract.getPayChannel()) && CollectionUtils.isNotEmpty(channelList)) {
                    List<PaymentChannelResponseDTO> filterList = channelList.stream().filter(c -> c.getPaymentChannelCode().equals(constract.getPayChannel())).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(filterList)) {
                        constract.setPayChannelCn(filterList.get(0).getPaymentChannelName());
                    }
                }
                constract.setInvoiceTypeCn(InvoiceTypeEnum.getDesc(constract.getInvoiceType()));
                // constract.setPayChannelCn(PaymentChannelEnum.getDesc(constract.getPayChannel()));
                constract.setOrderSourceCn(OrderSourceEnum.getDesc(constract.getOrderSource()));
            }

        }
//        pageInfo.getList().forEach(constract -> {
//            constract.setInvoiceTypeCn(InvoiceTypeEnum.getDesc(constract.getInvoiceType()));
//            constract.setPayChannelCn(PaymentChannelEnum.getDesc(constract.getPayChannel()));
//            constract.setOrderSourceCn(OrderSourceEnum.getDesc(constract.getOrderSource()));
//        });
        return pageInfo;
    }

    @Override
    public List<MerchantContract> findList(GetMerchantContractVO merchantVO) {
        QueryWrapper<MerchantContract> conditions = new QueryWrapper<MerchantContract>();
        conditions.eq("is_delete", "0");
        if (StringUtils.isNotEmpty(merchantVO.getContractCode())) {
            conditions.eq("contract_code", merchantVO.getContractCode());
        }
        if (StringUtils.isNotEmpty(merchantVO.getOrganizationName())) {
            conditions.likeLeft("organization_name", merchantVO.getOrganizationName());
        }
        if (StringUtils.isNotEmpty(merchantVO.getMerchantCode())) {
            conditions.eq("merchant_code", merchantVO.getMerchantCode());
        }
        if (StringUtils.isNotEmpty(merchantVO.getMerchantName())) {
            conditions.likeLeft("merchant_name", merchantVO.getMerchantName());
        }
        List<MerchantContract> list = merchantMapper.selectList(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            //取支付渠道
            Result<List<PaymentChannelResponseDTO>> channelBOList = paymentService.getAllChannel();
            List<PaymentChannelResponseDTO> channelList = new ArrayList<PaymentChannelResponseDTO>();
            if (channelBOList.getRet() == 0) {
                channelList = channelBOList.getData();
            }
            for (MerchantContract constract : list) {
                if (StringUtils.isNotEmpty(constract.getPayChannel()) && CollectionUtils.isNotEmpty(channelList)) {
                    List<PaymentChannelResponseDTO> filterList = channelList.stream().filter(c -> c.getPaymentChannelCode().equals(constract.getPayChannel())).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(filterList)) {
                        constract.setPayChannelCn(filterList.get(0).getPaymentChannelName());
                    }
                }
                constract.setInvoiceTypeCn(InvoiceTypeEnum.getDesc(constract.getInvoiceType()));
                // constract.setPayChannelCn(PaymentChannelEnum.getDesc(constract.getPayChannel()));
                constract.setOrderSourceCn(OrderSourceEnum.getDesc(constract.getOrderSource()));
            }

        }
        return list;
    }

    @Override
    public List<MerchantContract> findContractList(List<String> listStr) {
        return merchantMapper.findContractList(listStr);
    }

    @Override
    public List<MerchantContract> findEffectiveContract(List<String> listStr, String date) {
        return merchantMapper.findEffectiveContract(listStr, date);
    }

    public void test() {
        QueryWrapper<MerchantContract> conditions = new QueryWrapper<MerchantContract>();
        conditions.eq("contract_code", "");
        List<MerchantContract> mm = merchantMapper.selectList(conditions);
        int n = 0;
        for (MerchantContract con : mm) {
            con.setContractCode("ME-" + formart(++n));
            merchantMapper.updateById(con);
    		/* String content = product.getProductName() + String.valueOf(product.getCreatedDt()).substring(0, 19);
             product.setProductCode(DigestUtils.md5DigestAsHex(content.getBytes()).toUpperCase());
             productMapper.updateById(product);*/
        }
    }

    public String formart(int n) {
        NumberFormat formatter = NumberFormat.getNumberInstance();
        formatter.setMinimumIntegerDigits(4);
        formatter.setGroupingUsed(false);
        String s = formatter.format(n);
        return s;
    }


    @Transactional(rollbackFor = Exception.class)
    public int add(MerchantContract merchant) throws BusinessException {
        List<MerchantContract> merchantList = findMerchantByCode(merchant);
        Assert.isTrue(CollectionUtils.isEmpty(merchantList), "此商户已签过合同");
        if (CollectionUtils.isEmpty(merchantList)) {
            return merchantMapper.insert(merchant);
        }
        return 0;
    }

    /**
     * 修改商户信息时，先删除渠道信息，再重新保存
     * 同时修改清分规则中的商户名称
     *
     * @param merchant
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int update(MerchantContract merchant) throws BusinessException {
        List<MerchantContract> merchantList = findMerchantByCode(merchant);
        Assert.isTrue(CollectionUtils.isEmpty(merchantList), "此商户已签过合同");
        merchant.setVersion(null);
        merchant.setCreatedDt(null);
        merchant.setLastUpdDt(LocalDateTime.now());
        if (CollectionUtils.isEmpty(merchantList)) {
            return merchantMapper.updateById(merchant);
        }
        return 0;
    }

    /**
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int remove(Long id) {
        MerchantContract merchant = new MerchantContract();
        merchant.setId(id);
        merchant.setCreatedDt(null);
        merchant.setLastUpdDt(LocalDateTime.now());
        merchant.setIsDelete(1);
        QueryWrapper<MerchantContract> conditions = new QueryWrapper<MerchantContract>();
        conditions.eq("id", id);
        return merchantMapper.update(merchant, conditions);
    }

    @Override
    public List<MerchantContract> findContractByDate(List<String> listStr, String date) {
        return merchantMapper.findContractByDate(listStr, date);
    }

    @Override
    public List<MerchantContract> findContractByInDate(List<String> listStr, String date) {
        return merchantMapper.findContractByInDate(listStr, date);
    }

    /**
     * 按合同编号查询商户合同信息
     *
     * @param merchantVO
     * @return
     */
    private List<MerchantContract> findMerchantByCode(MerchantContract merchantVO) {
        List<MerchantContract> list = merchantMapper.findMerchantByCode(merchantVO);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(constract -> {
                constract.setInvoiceTypeCn(InvoiceTypeEnum.getDesc(constract.getInvoiceType()));
                constract.setPayChannelCn(PaymentChannelEnum.getDesc(constract.getPayChannel()));
                constract.setOrderSourceCn(OrderSourceEnum.getDesc(constract.getOrderSource()));
            });
        }
        return list;
    }


    /**
     * 商户合同信息导出
     *
     * @param merchantVO
     * @param request
     * @param response
     * @throws IOException
     */
    public void export(GetPageMerchantContractVO merchantVO, HttpServletRequest request, HttpServletResponse response) throws IOException {
        QueryWrapper<MerchantContract> conditions = new QueryWrapper<MerchantContract>();
        conditions.eq("is_delete", "0");
        conditions.select("contract_code", "organization_name", "organization_code", "merchant_name", "merchant_code", "order_source",
                "pay_channel", "product_qty", "amount", "invoice_type", "tax_rate", "contract_sign_date", "contract_start_date", "contract_end_date", "huilianyi_no");
        if (StringUtils.isNotBlank(merchantVO.getContractCode())) {
            conditions.eq("contract_code", merchantVO.getContractCode());
        }
        if (StringUtils.isNotBlank(merchantVO.getOrganizationName())) {
            conditions.like("organization_name", merchantVO.getOrganizationName());
        }
        if (StringUtils.isNotBlank(merchantVO.getMerchantName())) {
            conditions.like("merchant_name", merchantVO.getMerchantName());
        }
        if (StringUtils.isNotBlank(merchantVO.getOrderSource())) {
            conditions.eq("order_source", merchantVO.getOrderSource());
        }
        if (StringUtils.isNotBlank(merchantVO.getPayChannel())) {
            conditions.eq("pay_channel", merchantVO.getPayChannel());
        }
        if (StringUtils.isNotBlank(merchantVO.getInvoiceType())) {
            conditions.eq("invoice_type", merchantVO.getInvoiceType());
        }
        if (StringUtils.isNotBlank(merchantVO.getContractSignDate())) {
            conditions.eq("contract_sign_date", merchantVO.getContractSignDate());
        }
        if (StringUtils.isNotBlank(merchantVO.getContractStartDate())) {
            conditions.le("contract_start_date", merchantVO.getContractStartDate());
        }
        if (StringUtils.isNotBlank(merchantVO.getContractEndDate())) {
            conditions.ge("contract_end_date", merchantVO.getContractEndDate());
        }
        conditions.orderByDesc("created_dt");

        List<MerchantContract> list = merchantMapper.selectList(conditions);
        List<MerchantContractExpVO> contractList = new ArrayList<MerchantContractExpVO>();
        list.forEach(a -> {
            MerchantContractExpVO contractExpVO = ObjectConvertUtil.convert(a, MerchantContractExpVO.class).get();
            contractExpVO.setInvoiceType(InvoiceTypeEnum.getDesc(contractExpVO.getInvoiceType()));
            contractExpVO.setPayChannel(PaymentChannelEnum.getDesc(contractExpVO.getPayChannel()));
            contractExpVO.setOrderSource(OrderSourceEnum.getDesc(contractExpVO.getOrderSource()));
            contractExpVO.setTaxRate(String.valueOf(a.getTaxRate()) + "%");
            contractList.add(contractExpVO);
        });
        List<Map<String, Object>> mapList = listConvert(contractList);

        String fileName = "商户合同信息.xlsx";

        String[] title = {"合同编号", "所属机构", "机构编码", "商户名称", "商户编码", "业务场景", "支付渠道", "商品数量",
                "预付额度", "发票类型", "税率", "签订日期", "开始时间", "终止时间", "汇联易商户号"};
        Workbook workbook = ExcelUtil.buildWorkbook("商户合同信息", title, mapList);

        ExcelUtil.exportExcle(request, response, workbook, fileName);
    }

    /**
     * 数据转换
     *
     * @param list
     * @return
     */
    private List<Map<String, Object>> listConvert(List<MerchantContractExpVO> list) {
        List<Map<String, Object>> list_map = new ArrayList<Map<String, Object>>();
        try {
            for (MerchantContractExpVO t : list) {
                Field[] fields = t.getClass().getDeclaredFields();
                Map<String, Object> m = new LinkedHashMap<String, Object>();
                for (Field field : fields) {
                    String keyName = field.getName();
                    PropertyDescriptor pd = new PropertyDescriptor(keyName, t.getClass());
                    Method getMethod = pd.getReadMethod();// 获得getter方法
                    Object o = getMethod.invoke(t);// 执行get方法返回一个Object
                    m.put(keyName, o);
                }
                list_map.add(m);
            }
            return list_map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
